#include <stdio.h>
#include <math.h>
#include <limits.h>

// aplpha = 1/8
const float ALPHA = 0.125;
// beta = 4, default ist 0.25
const float BETA = 4;
// fuer die b), wie lange soll bei n geblieben werden
const int MAX_STAY_BY_N = 50;

// Estimated RTT = EstimatedRTT + (a * (SampleRTT - EstimatedRTT))
double calcEstimatedRtt(double sampleRtt, double* estimatedRtt){

	return *estimatedRtt + (ALPHA * (sampleRtt - *estimatedRtt));
}

// Deviation = Deviation + a * (|SampleRtt - EstimatedRtt| - Deviation)
double calcDeviation(double* deviation, double sampleRtt, double* estimatedRtt){

	return *deviation + ALPHA * (fabs(sampleRtt - *estimatedRtt) - *deviation);
}

//Timeout = EstimatedRtt + 4 * Deviation;
double clacTimeout(double* estimatedRtt, double* deviation){

	return *estimatedRtt + BETA * *deviation;
}

void calcAll(double sampleRtt, double* estimatedRtt, double* deviation, double* timeout){
	*estimatedRtt = calcEstimatedRtt(sampleRtt, estimatedRtt);
	*deviation = calcDeviation(deviation, sampleRtt, estimatedRtt);
	*timeout = clacTimeout(estimatedRtt, deviation);
}

// SampleRTT = 4.0 => SampleRTT = 1.0
void iterationCount(int n){

	double estimatedRtt = 0.0, sampleRtt = 4.0, deviation = 1.0;
	double timeout = clacTimeout(&estimatedRtt, &deviation);
	unsigned int itrCount = 0;

	int i;
	for(i = 0; i < n; i++){
		calcAll(sampleRtt, &estimatedRtt, &deviation, &timeout);
	}

	sampleRtt = 1.0;

	while(timeout > 4){
		calcAll(sampleRtt, &estimatedRtt, &deviation, &timeout);
		itrCount++;
	}

	printf("\n\n\n\nNach der %d Iteration ist der Timeout: %e\n\n", itrCount, timeout);

}

void estimateN(){
	double estimatedRtt = 0.0, sampleRtt = 1.0, deviation = 1.0;
	double timeout = clacTimeout(&estimatedRtt, &deviation);

	unsigned int itrCount = 0;
	unsigned int rounds = 0;
	unsigned int n = 1;

	while(n < INT_MAX){
			if(itrCount == n){// Das n-te Paket hat eine RTT von 4.0
				sampleRtt = 4.0;
				itrCount = 0;
				rounds++;
				if(rounds == MAX_STAY_BY_N){ // MAX_STAY_BY_N Durchlaeufe fuer ein n sind fertig
					n++;
					rounds = 0;
				}
				if(timeout < sampleRtt){ // Das Paket hatte ein Timeout
					printf("Timeout fuer n = %d.\n\n\n\n\n", n);
					break;
				}
			}
				//Berechnung
				calcAll(sampleRtt, &estimatedRtt, &deviation, &timeout);
				sampleRtt = 1.0;
				itrCount++;
			}
}

int main(int argc, char **args) {
	iterationCount(40);
  	estimateN();
	return 0;
}
